#include "projitem.h"

ProjGroup::ProjGroup(QWidget *p) : QFrame(p) {
    this->setObjectName("ProjGroup");
    initUI();
    initItemList();
    setAcceptDrops(true);
}

ProjGroup::~ProjGroup() {}

void ProjGroup::initUI () {
    _groupNameEdit = new QLineEdit(tr("Name"), this);
    _groupNameEdit->setMaximumHeight(40);
    _itemGdLay = new QGridLayout;
    _rmBtn = new QPushButton(this);
    _rmBtn->setObjectName("ProjGroup_RemoveBtn");

    QHBoxLayout *hb = new QHBoxLayout;
    hb->addWidget(_groupNameEdit);
    hb->addWidget(_rmBtn);
    QVBoxLayout *vb = new QVBoxLayout;
    // vb->addWidget (_groupNameEdit);
    vb->addLayout(hb);
    vb->addLayout (_itemGdLay);
    vb->addStretch();
    this->setLayout (vb);
    connect(_rmBtn, &QPushButton::clicked, this, [&] { removeGroup(this); });
}

QJsonObject ProjGroup::getJsonData() {
    QJsonObject obj;
    obj["Name"] = _groupNameEdit->text();
    QJsonArray jsonArr;
    for (int i = 0; i < _itemList.size(); i++) {
        jsonArr.append(_itemList.at(i)->getJsonData());
    }
    obj["ItemList"] = jsonArr;
    return obj;
}

void ProjGroup::initItemList () {
    _addProjBtn = new ProjItem(this);
    _itemGdLay->addWidget (_addProjBtn, 0, 0, 1, 1);
    connect(_addProjBtn, &ProjItem::clicked, this, &ProjGroup::addNewProjItem, Qt::QueuedConnection);
}

void ProjGroup::addNewProjItem() {
    auto strPath = QFileDialog::getOpenFileName(this, tr("Select Project"), "");
    if (strPath.isEmpty()) { return; }
    int count = _itemGdLay->count() - 1;
    ProjItem *addBtn = static_cast<ProjItem*>(_itemGdLay->itemAt(count)->widget());
    ProjItem *newItem = new ProjItem(this);
    connect(newItem, &ProjItem::deleteItem, this, &ProjGroup::deleteItem);
    newItem->setProjUrl(strPath);
    _itemGdLay->addWidget(newItem, count / 4, count % 4, 1, 1);
    _itemGdLay->removeWidget(addBtn);
    count += 1;
    _itemGdLay->addWidget(addBtn, count / 4, count % 4, 1, 1);
    _itemList.append(newItem);
}

void ProjGroup::addProjItem(const QString &path) {
    int count = _itemGdLay->count() - 1;
    ProjItem *addBtn = static_cast<ProjItem*>(_itemGdLay->itemAt(count)->widget());
    ProjItem *newItem = new ProjItem(this);
    connect(newItem, &ProjItem::deleteItem, this, &ProjGroup::deleteItem);
    newItem->setProjUrl(path);
    _itemGdLay->addWidget(newItem, count / 4, count % 4, 1, 1);
    _itemGdLay->removeWidget(addBtn);
    count += 1;
    _itemGdLay->addWidget(addBtn, count / 4, count % 4, 1, 1);
    _itemList.append(newItem);
}

void ProjGroup::addDropProjEvt(const QMimeData *data) {
    int count = _itemGdLay->count() - 1;
    ProjItem *addBtn = static_cast<ProjItem*>(_itemGdLay->itemAt(count)->widget());
    ProjItem *newItem = new ProjItem(this);
    connect(newItem, &ProjItem::deleteItem, this, &ProjGroup::deleteItem);
    _itemGdLay->addWidget(newItem, count / 4, count % 4, 1, 1);
    _itemGdLay->removeWidget(addBtn);
    count += 1;
    _itemGdLay->addWidget(addBtn, count / 4, count % 4, 1, 1);

    QList<QUrl> urls = data->urls();
    if (urls.isEmpty()) { return; }
    QString fileName = urls.first().toLocalFile();
    newItem->setProjUrl(fileName);
    _itemList.append(newItem);
}

void ProjGroup::deleteItem(ProjItem *item) {
    _itemGdLay->removeWidget(static_cast<QWidget*>(item));
    QLayoutItem *child;
    auto tmpLayout = _itemGdLay->layout();
    QList<QWidget*> list;
    while ((child = tmpLayout->takeAt(0)) != 0) {
        list.append(child->widget());
        tmpLayout->removeWidget(child->widget());
    }
    for (int i = 0; i < list.size(); i++) {
        _itemGdLay->addWidget(list.at(i), i / 4, i % 4, 1, 1);
    }

    int index = _itemList.indexOf(item);
    if (index != -1) { _itemList.removeAt(index); }

    item->deleteLater();
    item = nullptr;
}

void ProjGroup::dragEnterEvent(QDragEnterEvent *event) {
    if (event->mimeData()->hasFormat("text/uri-list")) {
        event->acceptProposedAction();
    } else if (event->mimeData()->text().indexOf("MoveToOtherGp") != -1) {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}

void ProjGroup::dropEvent(QDropEvent *event) {
    if (event->mimeData()->text().indexOf("MoveToOtherGp") != -1) {
        auto list = event->mimeData()->text().split(",");
        CMimeData *mData = (CMimeData*)event->mimeData();
        if (mData->parentWidget() == this) { return; }
        this->addProjItem(list.at(1));
        mData->parentWidget()->deleteItem(mData->thisWidget());
    } else {
        QList<QUrl> urls = event->mimeData()->urls();
        if (urls.isEmpty()) { return; }
        QString fileName = urls.first().toLocalFile();
        addDropProjEvt(event->mimeData());
    }
}

ProjItem::ProjItem(QWidget *p) : QToolButton(p) {
    this->setObjectName("ProjItem");
    initUI();
    initMenu();
    connect(this, &ProjItem::clicked, this, &ProjItem::runProj);
    _isPressed = false;
    _isDraged = false;
}

ProjItem::~ProjItem () {}

void ProjItem::initUI () {
    this->setFixedSize (70, 70);
    this->setText ("+");
    this->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
}

void ProjItem::initMenu() {
    _itemMenu = new QMenu(this);
    _openItem = new QAction(tr("Open"), this);
    _deleteItem = new QAction(tr("Delete"), this);
    _infoItem = new QAction(tr("Info"), this);

    _itemMenu->addAction(_openItem);
    _itemMenu->addAction(_infoItem);
    _itemMenu->addAction(_deleteItem);

    connect(_openItem, &QAction::triggered, [=]() { this->click(); });
    connect(_deleteItem, &QAction::triggered, [=]() { emit deleteItem(this); });
    connect(_infoItem, &QAction::triggered, [=] { 
        QToolTip::showText(QCursor::pos(), projUrl(), this);
    });
}

void ProjItem::runProj() {
    QDesktopServices::openUrl(QUrl::fromLocalFile(_projUrl));
}

void ProjItem::mousePressEvent(QMouseEvent *evt) {
    if (evt->button() == Qt::RightButton) {
        if (text() == "+") { return QToolButton::mousePressEvent(evt); }
        _itemMenu->exec(QCursor::pos());
        return;
    } else if (evt->button() == Qt::LeftButton) {
        _isPressed = true;
        _pressedPos = evt->globalPos() - pos();
    }
    return QToolButton::mousePressEvent(evt);
}

void ProjItem::mouseMoveEvent(QMouseEvent *evt) {
    if (_isPressed && text() != "+") {
        _isDraged = true;
        // this->move(evt->globalPos() - _pressedPos);
        QDrag *dg = new QDrag(this);
        CMimeData *mData = new CMimeData;
        mData->setText("MoveToOtherGp," + _projUrl);
        QIcon icon = this->icon();
        mData->setParentWidget(static_cast<ProjGroup*>(parentWidget()));
        mData->setThisWidget(this);
        dg->setMimeData(mData);
        QPixmap pmp(icon.pixmap(this->size()));
        QPainter pitr(&pmp);
        // pitr.drawText(QRect(0, this->height(), 120, 20), text(), QTextOption(Qt::AlignVCenter));
        dg->setPixmap(pmp);
        dg->setHotSpot(QPoint(10, 10));
        dg->exec(Qt::MoveAction);
    }
    return QToolButton::mouseMoveEvent(evt);
}

void ProjItem::mouseReleaseEvent(QMouseEvent *evt) {
    _isPressed = false;
    if (_isDraged) {
        parentWidget()->layout()->update();
        _isDraged = false;
        return;
    }
    _isDraged = false;
    return QToolButton::mouseReleaseEvent(evt);
}

void ProjItem::setProjUrl(QString url) {
    _projUrl = url;
    QFileInfo info(url);
    if (!info.exists()) { return; }
    QIcon fileIcon;
    if (isImage(url)) {
        fileIcon.addFile(url);
    } else {
        QFileIconProvider iconPri;
        fileIcon = iconPri.icon(info);
    }

    this->setIcon(fileIcon);
    this->setText(info.fileName());
    this->setToolTip(url);
}

bool ProjItem::isImage(const QString &file) {
    QList<QString> list = QStringList() 
        << ".png" << ".jpg" << ".bmp" << ".ico";
    for (int i = 0; i < list.size(); i++) {
        if (file.endsWith(list.at(i))) { return true; }
    }
    return false;
}

QJsonObject ProjItem::getJsonData() {
    QJsonObject obj;
    obj.insert("Path", _projUrl);
    return obj;
}
